#include <iostream>

using std::cout;
using std::endl;

class A{
    public:
        A():m_ptr(new int(0)){
            cout << "construct" << endl;
        }
        ~A() {
            cout << "destruct" << endl;
            delete m_ptr;
        }
        A(const A & a):m_ptr(new int(*a.m_ptr))
        {
            cout << "copy construct" << endl;
        }
        A(A&& a): m_ptr(a.m_ptr) //它的参数是一个右值引用类型 //如果是临时值，则会选择移动构造函数。
        {
            a.m_ptr = nullptr;
            cout << "move construct " << endl;
        }
        A& operator=(const A &&rhs);
    private:
        int * m_ptr;
};

A Get(bool flag)
{
    A a;
    A b;
    if(flag) //为什么临时值会调用移动构造
        return a;
    else
        return b;
}

int main(void)
{
    A g = Get(true); //从右边赋值的变量，不是右值吗？

    return 0;
}


//左值是指表达式在结束后依然存在的持久对象
//右值是指表达式结束时 不再存在的临时对象
//非引用返回的临时变量、运算表达式产生的临时变量，原始字面量和lambda 表达式都是纯右值
//将要移动的对象 T&& 函数的返回值 `std::move`返回值和转换为T&& 的类型的转换函数的返回值 都是将亡值
//可对表达式用 & 符取址，则为左值，否则为右值
//
//
//移动语义可以将资源（堆、系统对象等）通过浅拷贝方式从一个对象转移到另一个对象，这样能够减少不必要的临时对象的创建、拷贝以及销毁，可以大幅度提高c++应用程序的性能，消除临时对象的维护对性能的影响
//
//当赋值操作符的右边是右值的时候，我们希望赋值操作符被定义为
A& A::operator=(const A &&rhs)
{
    //转移资源的控制权，无须复制
}

//仅仅转移资源的所有者，将资源的拥有者改为赋值者，这就是所谓的move 语义
//使用move 实际上就是将左值转换右值引用，然后应用 move 语义调用构造函数，就避免了拷贝，提高了程序性能。move 对于形如拥有内存、文件句柄等资源的成员对象有效，如果是一些基本类型，比如int 和 char[10]，仍会发生拷贝
